﻿using System;
using System.IO;
using System.Data;
using System.Linq;
using System.Collections.Generic;
using System.Windows.Forms;
using Syncfusion.Windows.Forms.Tools;
using Syncfusion.Windows.Forms.Grid;
using Syncfusion.XlsIO;

using PMngr.Data;

namespace PMngr.Main
{
    public partial class Whole : BaseControl
    {
        private IRepositoryFactory repositoryFactory;
        private int recordCount;

        public Whole()
        {
            InitializeComponent();
            //
            InitializeGrid();
            //
            this.dtRecordDate.Value = DateTime.Now;
        }

        public Whole(IRepositoryFactory repositoryFactory)
            : this()
        {
            this.repositoryFactory = repositoryFactory;
        }

        public override void InitializeControls()
        {
            InitializeUnitType(this.comInUnitType);
            InitializeUnitType(this.comOutUnitType);
            InitializeUpUnitComboBox(this.comInUpUnit);
            InitializeUpUnitComboBox(this.comOutUpUnit);
            InitializeUnitComboBox(this.comInUnit);
            InitializeUnitComboBox(this.comOutUnit);

            comInUnitType.SelectedIndexChanged += new System.EventHandler(this.comInUnitType_SelectedIndexChanged);
            comOutUnitType.SelectedIndexChanged += new System.EventHandler(this.comOutUnitType_SelectedIndexChanged);

            comInUpUnit.SelectionChangeCommitted += new EventHandler(comInUpUnit_SelectionChangeCommitted);
            comOutUpUnit.SelectionChangeCommitted += new EventHandler(comOutUpUnit_SelectionChangeCommitted);
        }

        private void InitializeGrid()
        {
            gridList.Model.ReadOnly = true; 
        }

        private void InitializeUnitType(ComboBoxAdv com)
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                // 单位区域
                var options = repository.All<ItemBase>();
                var datasource = from o in options
                                 where o.Type == "UnitType" && o.IsValid == true
                                 orderby o.Order ascending
                                 select new {Code = o.Code, Name = o.Name};
                var result = datasource.ToList();
                result.Insert(0, new {Code = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName});
                com.DataSource = result;
                com.DisplayMember = ItemModel.GetPropertyName(u => u.Name);
                com.ValueMember = ItemModel.GetPropertyName(u => u.Code);
            }
        }

        private void UpUnitSelectedIndexChanged(ComboBoxAdv comAdv, MultiColumnComboBox com)
        {
            var defaultValue = DefaultAll.DefaultValue;
            var unitType = comAdv.SelectedValue;
            // 单位
            if ((int)unitType == defaultValue)
            {
                InitializeUpUnitComboBox(com);
            }
            else
            {
                using (var repository = repositoryFactory.CreateRepository())
                {
                    var units = repository.Find<Unit>(u => u.ParentUnit == null && u.UnitType.Code == (int) unitType);
                    var datasource = from u in units
                                     select new {Id = u.Id, Name = u.Name};

                    var result = datasource.ToList();
                    result.Insert(0, new {Id = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName});
                    com.DataSource = result;
                    com.DisplayMember = UnitModel.GetPropertyName(u => u.Name);
                    com.ValueMember = UnitModel.GetPropertyName(u => u.Id);
                }
            }
        }

        private void comInUnitType_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpUnitSelectedIndexChanged(comInUnitType, comInUpUnit);           
        }

        private void comOutUnitType_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpUnitSelectedIndexChanged(comOutUnitType, comOutUpUnit);           
        }

        private void SelectedIndexChanged(MultiColumnComboBox upCom, MultiColumnComboBox com)
        {
            var defaultValue = DefaultAll.DefaultValue;
            var upUnit = upCom.SelectedValue;
            // 主管部门
            if ((int)upUnit == defaultValue)
            {
                InitializeUnitComboBox(com);
            }
            else
            {
                using (var repository = repositoryFactory.CreateRepository())
                {
                    var units =
                        repository.Find<Unit>(
                            item => item.IsValid && item.ParentUnit != null && item.ParentUnit.Id == (int) upUnit);
                    var datasource = from u in units
                                     select new {Id = u.Id, Name = u.Name};

                    var result = datasource.ToList();
                    result.Insert(0, new {Id = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName});
                    com.DataSource = result;
                    com.DisplayMember = UnitModel.GetPropertyName(u => u.Name);
                    com.ValueMember = UnitModel.GetPropertyName(u => u.Id);
                }
            }
        }

        private void comInUpUnit_SelectionChangeCommitted(object sender, EventArgs e)
        {
            SelectedIndexChanged(comInUpUnit, comInUnit);
        }

        private void comOutUpUnit_SelectionChangeCommitted(object sender, EventArgs e)
        {
            SelectedIndexChanged(comOutUpUnit, comOutUnit);
        }

        private void InitializeUpUnitComboBox(MultiColumnComboBox com)
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                // 主管部门
                var units = repository.Find<Unit>(u => u.IsValid && u.ParentUnit == null);
                var datasource = from u in units
                                 select new {Id = u.Id, Name = u.Name};

                var result = datasource.ToList();
                result.Insert(0, new {Id = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName});
                com.DataSource = result;
                com.DisplayMember = UnitModel.GetPropertyName(u => u.Name);
                com.ValueMember = UnitModel.GetPropertyName(u => u.Id);
            }
            // settings
            GridControl grid = com.ListBox.Grid;
            grid.Cols.DefaultSize = 230;
            grid.HideCols[UnitModel.GetPropertyName(u => u.Id)] = true;

            grid.PrepareViewStyleInfo += new GridPrepareViewStyleInfoEventHandler(gridListUp_PrepareViewStyleInfo);
        }

        private void gridListUp_PrepareViewStyleInfo(object sender, GridPrepareViewStyleInfoEventArgs e)
        {
            if (e.ColIndex == 2 && e.RowIndex == 0)
            {
                e.Style.Text = Utilities.MajorUnitSelected;
            }
        }

        private void InitializeUnitComboBox(MultiColumnComboBox com)
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                // 单位
                var units = repository.Find<Unit>(u => u.IsValid && u.ParentUnit != null);
                var datasource = from u in units
                                 select new {Id = u.Id, Name = u.Name};

                var result = datasource.ToList();
                result.Insert(0, new {Id = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName});
                com.DataSource = result;
                com.DisplayMember = UnitModel.GetPropertyName(u => u.Name);
                com.ValueMember = UnitModel.GetPropertyName(u => u.Id);
            }
            // settings
            GridControl grid = com.ListBox.Grid;
            grid.Cols.DefaultSize = 230;
            grid.HideCols[UnitModel.GetPropertyName(u => u.Id)] = true;
            grid.PrepareViewStyleInfo += new GridPrepareViewStyleInfoEventHandler(gridList_PrepareViewStyleInfo);
        }

        private void gridList_PrepareViewStyleInfo(object sender, GridPrepareViewStyleInfoEventArgs e)
        {
            if (e.ColIndex == 2 && e.RowIndex == 0)
            {
                e.Style.Text = Utilities.UnitSelected;
            }
        }

        private void btnFile_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK && openFileDialog.CheckPathExists)
            {
                this.txtFile.Text = openFileDialog.FileName;
                // import profiles
                GetProfiles(this.txtFile.Text);
                //
                this.btnImport.Enabled = true;
            }           
        }

        // false -> 调入, true ->调出
        private bool GetTransferKind()
        {
            if (rdoIn.Checked)
                return false;

            return true;
        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            var inUnit = this.comInUnit.Text;
            var outUnit = this.comOutUnit.Text;
            var file = this.txtFile.Text;
            if (String.IsNullOrWhiteSpace(file))
            {
                MessageFactory.Show(Utilities.FirstImportFile, MessageBoxIcon.Exclamation);
                return;
            }
            if (String.IsNullOrWhiteSpace(inUnit) || String.IsNullOrWhiteSpace(outUnit) || inUnit == DefaultAll.DefaultName || outUnit == DefaultAll.DefaultName)
            {
                MessageFactory.Show(Utilities.InOutUnitRequired, MessageBoxIcon.Exclamation);
                return;
            }
            if (String.Compare(inUnit,outUnit) == 0)
            {
                MessageFactory.Show(Utilities.InOutUnitIdentical, MessageBoxIcon.Exclamation);
                return;
            }            // save the wholetransfer object
            try
            {
                using (var repository = repositoryFactory.CreateRepository())
                {
                    WholeTransfer wt = new WholeTransfer();
                    var filename = Path.GetFileName(file);
                    wt.TransferFile = String.Format("{0}_{1}_{2}", inUnit, filename, DateTime.Today.ToString("yyyyMMdd"));
                    wt.RecordDate = this.dtRecordDate.Value;
                    wt.Description = String.Format(Utilities.ImportPrompt, filename, recordCount);
                    wt.InUnit = inUnit;
                    wt.OutUnit = outUnit;
                    wt.TransferKind = GetTransferKind();
                    wt.Profiles = new List<Profile>();
                    repository.Add<WholeTransfer>(wt);
                    // save the profile 
                    SaveProfiles(repository, inUnit, outUnit, wt);
                    //
                    repository.CommitChanges();
                    //
                    this.btnImport.Enabled = false;
                    //
                    LogTrace(wt.Description, MessageType.Information);
                }
            }
            catch (Exception ex)
            {
                LogTrace(ex.Message, MessageType.Error);
            }
        }

        private void SaveProfiles(IRepository repository, string inUnit, string outUnit, WholeTransfer wt)
        {
            var data = this.gridList.DataSource as DataTable;

            foreach (DataRow row in data.Rows)
            {
                Profile profile = new Profile();
                profile.Name = GetString(row, 0);
                profile.Nationality = GetString(row, 1);
                profile.BirthDate = GetDate(row, 2);
                profile.Gender = GetString(row, 3);
                profile.NativePlace = GetString(row, 4);

                profile.SchoolRecord = GetItemBaseInstance(repository, row, 5, "SchoolRecord");
                profile.SchoolLevel = GetItemBaseInstance(repository, row, 6, "SchoolLevel");
                profile.PolicyFace = GetItemBaseInstance(repository, row, 7, "PolicyFace");

                profile.College = GetString(row, 8);
                profile.Major = GetString(row, 9);
                profile.HomeTown = GetString(row, 10);

                profile.PersonalIdentity = GetItemBaseInstance(repository, row, 11, "Identity");
                profile.ProfPos = GetString(row, 12);
                profile.ProfTitle = GetString(row, 13);
                profile.TechGrade = GetItemBaseInstance(repository, row, 14, "TechGrade");
                profile.WorkKind = GetString(row, 15);
                profile.WorkStart = GetDate(row, 16);
                profile.Family = GetString(row, 17);
                profile.Remark1 = GetString(row, 18);
                profile.Remark2 = GetString(row, 19);
                //
                profile.TransferReason = GetItemBaseInstance(repository, "整体划转", "TransCause");
                //
                profile.InUnit = GetUnitInstance(repository, inUnit);
                profile.OutUnit = GetUnitInstance(repository, outUnit);
                //
                profile.OriginalIn = profile.InUnit.Name;
                profile.OriginalOut = profile.OutUnit.Name;
                profile.OriginalInUpUnit = profile.InUnit.ParentUnit.Name;
                profile.OriginalOutUpUnit = profile.OutUnit.ParentUnit.Name;
                profile.OriginalInUnitKind = profile.InUnit.UnitType.Name;
                profile.OriginalInUnitType = profile.InUnit.ParentUnit.UnitType.Name;
                profile.OriginalOutUnitKind = profile.OutUnit.UnitType.Name;
                profile.OriginalOutUnitType = profile.OutUnit.ParentUnit.UnitType.Name;
                // the same to the WholeTransfer RecordDate                
                profile.RecordDate = wt.RecordDate;
                //
                repository.Add<Profile>(profile);
                wt.Profiles.Add(profile);
            }
        }

        private string GetString(DataRow row, int index)
        {
            var obj = row[index];
            var result = obj == null ? "" : obj.ToString();
            return result;
        }
        private DateTime? GetDate(DataRow row, int index)
        {
            DateTime result;
            var obj = row[index];
            var date = obj.ToString();
            if (DateTime.TryParse(date, out result))
                return result;
            return null;
        }

        private ItemBase GetItemBaseInstance(IRepository repository, string name, string type)
        {
            ItemBase item = repository.Single<ItemBase>(i => i.Type == type && i.Name == name);
            return item;
        }
        private ItemBase GetItemBaseInstance(IRepository repository, DataRow row, int index, string type)
        {
            var obj = row[index];
            if (obj != null)
            {
                var name = obj.ToString();
                ItemBase item = repository.Single<ItemBase>(i => i.Type == type && i.Name == name);
                return item;
            }
            return null;
        }
        private Unit GetUnitInstance(IRepository repository, string name)
        {
            var unit = repository.Single<Unit>(i => i.Name == name && i.ParentUnit != null);
            return unit;
        }

        private void GetProfiles(string file)
        {
            try
            {
                //Step 1 : Instantiate the spreadsheet creation engine.
                ExcelEngine excelEngine = new ExcelEngine();
                //Step 2 : Instantiate the excel application object.
                IApplication application = excelEngine.Excel;
                IWorkbook workbook = application.Workbooks.Open(file);
                //The first worksheet object in the worksheets collection is accessed.
                IWorksheet sheet = workbook.Worksheets[0];
                sheet.UsedRangeIncludesFormatting = false;
                //Read data from spreadsheet.
                DataTable data = sheet.ExportDataTable(sheet.UsedRange, ExcelExportDataTableOptions.ColumnNames);
                this.gridList.DataSource = data;
                recordCount = data.Rows.Count;
                //Close the workbook.
                workbook.Close();
                //No exception will be thrown if there are unsaved workbooks.
                excelEngine.ThrowNotSavedOnDestroy = false;
                excelEngine.Dispose();
            }
            catch
            {
                LogTrace(Utilities.ImportError, MessageType.Exclamation);
                return;
            }
        }

    }
}
